package com.chinackts.config;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import javax.annotation.Resource;

/**
 * @author Lianhong
 * @since 2021/1/12
 */
@Configuration
public class RedisConfiguration {

    @Resource
    private RedisProperties redisProperties;

    @Bean
    public GenericObjectPoolConfig<?> genericObjectPoolConfig() {
        GenericObjectPoolConfig<?> config = new GenericObjectPoolConfig<>();
        config.setMinIdle(redisProperties.getLettuce().getPool().getMaxIdle());
        config.setMaxIdle(redisProperties.getLettuce().getPool().getMaxIdle());
        config.setMaxTotal(redisProperties.getLettuce().getPool().getMaxActive());
        config.setMaxWaitMillis(redisProperties.getLettuce().getPool().getMaxWait().toMillis());
        return config;
    }

    @Bean
    public RedisStandaloneConfiguration configurationDB1() {
        RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(redisProperties.getHost(), redisProperties.getPort());
        configuration.setPassword(RedisPassword.of(redisProperties.getPassword()));
        configuration.setDatabase(10);
        return configuration;
    }

    @Bean
    public RedisStandaloneConfiguration configurationDB2() {
        RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(redisProperties.getHost(), redisProperties.getPort());
        configuration.setPassword(RedisPassword.of(redisProperties.getPassword()));
        configuration.setDatabase(12);
        return configuration;
    }

    @Primary
    @Bean("factory1")
    public LettuceConnectionFactory factory1(@Qualifier("genericObjectPoolConfig") GenericObjectPoolConfig<?> poolConfig,
                                             @Qualifier("configurationDB1") RedisStandaloneConfiguration configuration) {
        LettuceClientConfiguration clientConfiguration = LettucePoolingClientConfiguration
                .builder().poolConfig(poolConfig).build();
        return new LettuceConnectionFactory(configuration, clientConfiguration);
    }

    @Bean("factory2")
    public LettuceConnectionFactory factory2(@Qualifier("genericObjectPoolConfig") GenericObjectPoolConfig<?> poolConfig,
                                             @Qualifier("configurationDB2") RedisStandaloneConfiguration configuration) {
        LettuceClientConfiguration clientConfiguration = LettucePoolingClientConfiguration
                .builder().poolConfig(poolConfig).build();
        return new LettuceConnectionFactory(configuration, clientConfiguration);
    }

    @Primary
    @Bean
    public StringRedisTemplate redisTemplate1(@Qualifier("factory1") LettuceConnectionFactory factory) {
        StringRedisTemplate redisTemplate = new StringRedisTemplate();
        redisTemplate.setConnectionFactory(factory);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    @Bean
    public StringRedisTemplate redisTemplate2(@Qualifier("factory2") LettuceConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(factory);
        template.afterPropertiesSet();
        return template;
    }


    // 新增RedissonClient配置 - 使用DB1
    @Primary
    @Bean(destroyMethod = "shutdown")
    public RedissonClient redissonClient1() {
        Config config = new Config();
        SingleServerConfig serverConfig = config.useSingleServer()
                .setAddress("redis://" + redisProperties.getHost() + ":" + redisProperties.getPort())
                .setDatabase(10)  // 使用DB1
                .setTimeout((int) redisProperties.getTimeout().toMillis())
                .setConnectionPoolSize(redisProperties.getLettuce().getPool().getMaxActive())
                .setConnectionMinimumIdleSize(redisProperties.getLettuce().getPool().getMinIdle());

        if (redisProperties.getPassword() != null) {
            serverConfig.setPassword(redisProperties.getPassword());
        }

        return Redisson.create(config);
    }

    // 新增RedissonClient配置 - 使用DB2
    @Bean(destroyMethod = "shutdown")
    public RedissonClient redissonClient2() {
        Config config = new Config();
        SingleServerConfig serverConfig = config.useSingleServer()
                .setAddress("redis://" + redisProperties.getHost() + ":" + redisProperties.getPort())
                .setDatabase(12)  // 使用DB2
                .setTimeout((int) redisProperties.getTimeout().toMillis())
                .setConnectionPoolSize(redisProperties.getLettuce().getPool().getMaxActive())
                .setConnectionMinimumIdleSize(redisProperties.getLettuce().getPool().getMinIdle());

        if (redisProperties.getPassword() != null) {
            serverConfig.setPassword(redisProperties.getPassword());
        }

        return Redisson.create(config);
    }
}
